package 中等.模拟;

/**
 * 你正在经营一座摩天轮，该摩天轮共有 4 个座舱 ，每个座舱 最多可以容纳 4
 * 位游客 。你可以 逆时针 轮转座舱，但每次轮转都需要支付一定的运行成本
 * runningCost 。摩天轮每次轮转都恰好转动 1 / 4 周。
 * 给你一个长度为 n 的数组 customers ， customers[i] 是在第 i 次轮转
 * （下标从 0 开始）之前到达的新游客的数量。这也意味着你必须在新游客到
 * 来前轮转 i 次。每位游客在登上离地面最近的座舱前都会支付登舱成本 boardingCost
 * ，一旦该座舱再次抵达地面，他们就会离开座舱结束游玩。
 * 你可以随时停下摩天轮，即便是 在服务所有游客之前 。如果你决定停止运
 * 营摩天轮，为了保证所有游客安全着陆，将免费进行所有后续轮转 。注意，
 * 如果有超过 4 位游客在等摩天轮，那么只有 4 位游客可以登上摩天轮，其余的需要等待 下一次轮转 。
 * 返回最大化利润所需执行的 最小轮转次数 。 如果不存在利润为正的方案，则返回 -1 。
 * <p>
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode.cn/problems/maximum-profit-of-operating-a-centennial-wheel
 */
public class 经营摩天轮的最大利润_1599 {

    public static void main(String[] args) {

        System.out.println(minOperationsMaxProfit(new int[]{8, 3}, 5, 6));

    }

    /**
     * 模拟
     * 需要记录上一次留下来的乘客，尽可能多乘客上摩天轮
     * 如果遍历到最后任然有乘客在等待，也需要考虑
     * 注意：当前摩天轮贴地座舱一定可以容纳 4 位乘客，先下后上
     */
    public static int minOperationsMaxProfit(int[] customers, int boardingCost, int runningCost) {
        int maxOp = 0, maxCost = -1;
        int curOp = 0, curCost = 0, curCustomer = 0;
        for (int customer : customers) {
            curOp++;
            int boardingCnt;
            curCustomer += customer;
            if (curCustomer >= 4) {
                curCustomer -= 4;
                boardingCnt = 4;
            } else {
                boardingCnt = curCustomer;
                curCustomer = 0;
            }
            curCost += boardingCnt * boardingCost - runningCost;

            if (curCost > maxCost) {
                maxCost = curCost;
                maxOp = curOp;
            }
        }
        if (4 * boardingCost > runningCost) {
            curCost += (curCustomer / 4) * (4 * boardingCost - runningCost);
            curOp += curCustomer / 4;
            if (curCost > maxCost) {
                maxCost = curCost;
                maxOp = curOp;
            }
        }
        if (curCustomer % 4 * boardingCost > runningCost) {
            curCost += curCustomer % 4 * boardingCost - runningCost;
            curOp++;
            if (curCost > maxCost) {
                maxCost = curCost;
                maxOp = curOp;
            }
        }

        return maxCost > 0 ? maxOp : -1;
    }

    /**
     * 模拟
     */
    public static int minOperationsMaxProfit2(int[] customers, int boardingCost, int runningCost) {
        if (customers.length == 0) return 0;
        int maxProfit = 0, curCustom = 0, curProfit = 0;
        int idx = 0;
        int maxCnt = -1, curCnt = 1;
        while (idx < customers.length || curCustom > 0) {
            if (idx < customers.length) {
                curCustom += customers[idx];
                idx++;
            }
            // 登上摩天轮前就会付钱
            Integer num = Math.min(4, curCustom);
            curProfit += num * boardingCost - runningCost;

            curCustom = Math.max(0, curCustom - 4);

            if (curProfit > maxProfit && curProfit >= 0) {
                maxProfit = curProfit;
                maxCnt = curCnt;
            }
            curCnt++;
        }

        return maxCnt;
    }

}
